Como comprobar el nivel de la batería que estamos usando para alimentar el microcontrolador.
Para comprobar el estado de la batería lo hacemos leyendo el voltaje de la batería usando el ADC.
Para leer el votaje de la batería que alimenta el propio microcontrolador lo hacemos usando el voltaje de referencia interno del microcontrolador de 1.1v
Primero iniciamos el ADC para que lea el voltaje de AVCC en relación al voltaje interno:
ADMUX |= (1 << REFS0) | (1 << MUX3) | (1 << MUX2) | (1 << MUX1); // Leemos el valor de AVCC en referencia al voltaje interno de 1.1v
ADCSRA |= (1 << ADPS1) | (1 << ADPS2); // Configuramos prescaler
ADCSRA |= (1 << ADEN); // Activamos el ADC
Ahora solo tenemos que hacer una lectura del ADC como siempre:
ADCSRA |= (1 << ADSC);
loop_until_bit_is_clear(ADCSRA, ADSC);
Ahora tenemos que interpretar el valor del ADC para saber el porcentaje exacto de la batería.
Conectamos Vcc al AVCC y AREF lo conectamos a tierra usando un condensador de 100nf.
Los leds del esquema se usan para mostrar el voltaje en valor binario.
Cuando hacemos una lectura del ADC usando el voltaje de referencia interno (1.1v), el valor que devuelve el ADC será de 1023 si el voltaje que tenemos en AVCC es de 1.1V, a partir de aquí el valor del ADC disminuye a medida que el voltaje aumenta, si obtenemos una lectura de 512 el voltaje será de 2.2v, si obtenemos una lectura de 256 el voltaje será de 4.4v, de este modo podemos saber que valores del ADC corresponden con los valores de voltajes leidos en AVCC (el voltaje de nuestra batería).
Calculo de valor del ADC para un voltaje:
1023/ (voltaje / 1.1)
Si por ejemplo tenemos un voltaje de 5v, lo dividimos entre 1.1v y despues dividimos 1023 entre el resultado anterior, en este caso haríamos 1023/(5/1.1), lo que nos da unos 225.
A la hora de calcular el porcentaje que le queda a nuestra batería necesitamos los siguientes valores:
Por ejemplo para una pila AA el voltaje máximo es de 1.6v y el minimo es de 1.1v, para alimentar el microcontrolador usamos dos pilas AA, lo que nos deja un voltaje máximo de 3.2v y un voltaje minimo de 2.2v, ahora necesitamos saber a que valores del ADC corresponden esos voltajes, el voltaje máximo sería (1023/(3.2/1.1)) que es 351 y para el voltaje mínimo sería (1023/(2.2/1.1)) que es 511.
Por lo tanto con estos valores sabremos que al leer 351 la batería está al máximo de su capacidad y al leer 511 está al mínimo.
Para transformarlo a porcentaje (%) lo hacemos con la siguiente formula
(ADC_MAXIMO - VALOR_ADC) * 100 / DIFERENCIA_MAX-MIN;
En el ejemplo de las dos pilas AA si estamos leyendo un valor de 420 el cálculo sería, ((511 - 420) * 100) / 160, el 160 es la diferencia entre 511 y 351, en este caso nos daría un valor de 56%
Al hacer varias lecturas del voltaje a veces puede ir fluctuando entre varios valores, esto producirá que el porcentaje de nuestra batería a veces lo leamos como 82 por ejemplo y a los pocos segundos como 83, para evitar esto podemos usar una variable que solo muestre el valor mas bajo que se haya leido:
volatile uint8_t min_battery = 100;
int8_t get_battery(){
ADCSRA |= (1 << ADSC);
loop_until_bit_is_clear(ADCSRA, ADSC);
uint8_t battery_level = (ADC_MAX_VALUE - ADC) * 100 / ADC_DIFF_MAX_MIN;
if(battery_level < min_battery){
min_battery = battery_level;
}
return min_battery;
}
Leemos el nivel de la batería y lo mostramos como valor binario en 8 leds.
#include <avr/power.h>
#define ADC_MAX_VALUE 511
#define ADC_DIFF_MAX_MIN 160
volatile uint8_t min_battery = 100;
void adc_init(){
ADMUX |= (1 << REFS0) | (1 << MUX3) | (1 << MUX2) | (1 << MUX1);
ADCSRA |= (1 << ADPS1) | (1 << ADPS2);
ADCSRA |= (1 << ADEN);
}
int8_t get_battery(){
ADCSRA |= (1 << ADSC);
loop_until_bit_is_clear(ADCSRA, ADSC);
uint8_t battery_level = (ADC_MAX_VALUE - ADC) * 100 / ADC_DIFF_MAX_MIN;
if(battery_level < min_battery){
min_battery = battery_level;
}
return min_battery;
}
int main(void) {
clock_prescale_set(clock_div_1);
DDRB = 0xFF;
adc_init();
while (1) {
PORTB = get_battery();
}
}
AVR | microcontrolador | batería